package art.java.concurrency.chapter05;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author <a href="eric_zheng@lanzuo.com.cn">eric</a>
 * @version 1.0.0
 * Description:
 */
public class BoundedQueue<T> {
    /**
     * 定义一个数组来存储元素
     */
    private Object[] items;

    /**
     * 添加的下标
     */
    private int addIndex;

    /**
     * 删除的下标
     */
    private int removeIndex;

    /**
     * 数量
     */
    private int count;

    private Lock lock = new ReentrantLock();

    private Condition full = lock.newCondition();

    private Condition empty = lock.newCondition();

    /**
     * 初始化数组
     *
     * @param size 数组长度
     */
    public BoundedQueue(int size) {
        items = new Object[size];
    }


    public void add(T t) {
        lock.lock();
        try {
            // 当数量与元素长度相等时
            while (count == items.length) {
                // 说明数组已满，让条件为空的等一会
                empty.wait();
            }
            // 加入元素
            items[addIndex] = t;
            if (++addIndex == items.length) {
                addIndex = 0;
            }
            ++count;
            full.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 删除头部元素，如果数组为空，则删除线程进入等待状态，直至有新元素添加
     *
     * @return t
     */
    public T remove() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                full.await();
            }
            Object x = items[removeIndex];
            if (++removeIndex == items.length) {
                removeIndex = 0;
            }
            --count;
            empty.signal();
            return (T) x;


        } finally {
            lock.unlock();
        }

    }

}
